package Chapter1.array;

import java.util.Arrays;

public class CircleArray<T> {
    public static void main(String[] args) {
        CircleArray<Integer> integerCircleArray = new CircleArray<>();
        integerCircleArray.addFirst(1);
        integerCircleArray.addFirst(2);
        integerCircleArray.addFirst(3);
        integerCircleArray.addFirst(3);

        System.out.println(integerCircleArray.toString());
    }

    private T[] table;
    private int size;
    private int count;
    private int start;
    private int end;

    public CircleArray() {
        this(1);
    }

    public CircleArray(int size) {
        this.size = size;
        this.table = (T[]) new Object[size];
        this.count = 0;

        this.start = 0;
        this.end = 0;
    }

    public void addFirst(T value) {
        if (isFull()) {
            resize(size * 2);
        }
        start = (start - 1 + size) % size;
        table[start] = value;
//        end = count + 1;
        count++;
    }

    public void removeFirst() {
        table[start] = null;
        start = (start + 1) % size;
        count--;
        for (int i = start; i <= end; i--) {
            table[i] = table[i + 1];
        }
        // 如果数组元素数量减少到原大小的四分之一，则减小数组大小为一半
        if (count > 0 && count == size / 4) {
            resize(size / 2);
        }
    }

    public void addLast(T value) {
        end = (end + 1) % size;
        table[end] = value;
        count++;
    }

    public void removeLast() {
        end = (end - 1 + size) % size;
        table[end] = null;
        count--;
    }

    public T getFirst() {
        return table[start];
    }

    public T getLast() {
        if (isEmpty()) {
            throw new IllegalStateException("Array is empty");
        }
        // end 是开区间，指向的是下一个元素的位置，所以要减 1
        return table[(end - 1 + size) % size];
    }

    public boolean isEmpty() {
        return count == 0;
    }


    public boolean isFull() {
        return count == size;
    }

    public void resize(int newSize) {
        T[] newTable = (T[]) new Object[newSize];
        for (int i = 0; i < count; i++) {
            newTable[i] = table[(start + i) % size];
        }
        this.table = newTable;
        start = 0;
        end = count;
        size = newSize;
    }

    @Override
    public String toString() {
        return "CircleArray{" +
                "table=" + Arrays.toString(table) +
                ", size=" + size +
                ", count=" + count +
                ", start=" + start +
                ", end=" + end +
                '}';
    }
}
